home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 21 / CU Amiga Magazine's Super CD-ROM 21 (1998)(EMAP Images)(GB)[!][issue 1998-04].iso / CUCD / Programming / Python-1.4 / Python1.4_Source / Modules / selectmodule.c < prev    next >
C/C++ Source or Header  |  1996-12-15  |  9KB  |  353 lines

  1. /***********************************************************
  2. Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
  3. The Netherlands.
  4.  
  5.                         All Rights Reserved
  6.  
  7. Permission to use, copy, modify, and distribute this software and its
  8. documentation for any purpose and without fee is hereby granted,
  9. provided that the above copyright notice appear in all copies and that
  10. both that copyright notice and this permission notice appear in
  11. supporting documentation, and that the names of Stichting Mathematisch
  12. Centrum or CWI or Corporation for National Research Initiatives or
  13. CNRI not be used in advertising or publicity pertaining to
  14. distribution of the software without specific, written prior
  15. permission.
  16.  
  17. While CWI is the initial source for this software, a modified version
  18. is made available by the Corporation for National Research Initiatives
  19. (CNRI) at the Internet address ftp://ftp.python.org.
  20.  
  21. STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
  22. REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
  23. MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
  24. CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
  25. DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  26. PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  27. TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  28. PERFORMANCE OF THIS SOFTWARE.
  29.  
  30. ******************************************************************/
  31.  
  32. /* select - Module containing unix select(2) call.
  33. Under Unix, the file descriptors are small integers.
  34. Under Win32, select only exists for sockets, and sockets may
  35. have any value except INVALID_SOCKET.
  36. */
  37.  
  38. #include "allobjects.h"
  39. #include "modsupport.h"
  40. #include "ceval.h"
  41.  
  42. #include <sys/types.h>
  43.  
  44. #ifdef MS_WINDOWS
  45. #include <winsock.h>
  46. #else
  47. #include "myselect.h" /* Also includes mytime.h */
  48. #define SOCKET int
  49. #endif
  50.  
  51. static object *SelectError;
  52.  
  53. typedef struct {    /* list of Python objects and their file descriptor */
  54.     object *obj;
  55.     SOCKET fd;
  56. } pylist;
  57.  
  58. #include "protos/selectmodule_protos.h"
  59.  
  60. static int
  61. list2set(list, set, fd2obj)
  62.     object *list;
  63.     fd_set *set;
  64.     pylist fd2obj[FD_SETSIZE + 3];
  65. {
  66.     int i, len, index, max = -1;
  67.     object *o, *filenomethod, *fno;
  68.     SOCKET v;
  69.  
  70.     index = 0;
  71.     fd2obj[0].obj = (object*)0;    /* set list to zero size */
  72.     
  73.     FD_ZERO(set);
  74.     len = getlistsize(list);
  75.     for( i=0; i<len; i++ ) {
  76.     o = getlistitem(list, i);
  77.     if ( is_intobject(o) ) {
  78.         v = getintvalue(o);
  79.     } else if ( (filenomethod = getattr(o, "fileno")) != NULL ) {
  80.         fno = call_object(filenomethod, NULL);
  81.         DECREF(filenomethod);
  82.         if ( fno == NULL )
  83.         return -1;
  84.         if ( !is_intobject(fno) ) {
  85.         err_badarg();
  86.         DECREF(fno);
  87.         return -1;
  88.         }
  89.         v = getintvalue(fno);
  90.         DECREF(fno);
  91.     } else {
  92.         err_badarg();
  93.         return -1;
  94.     }
  95. #ifdef _MSC_VER
  96.     max = 0;    /* not used for Win32 */
  97. #else
  98.     if ( v < 0 || v >= FD_SETSIZE ) {
  99.         err_setstr(ValueError, "filedescriptor out of range in select()");
  100.         return -1;
  101.     }
  102.     if ( v > max ) max = v;
  103. #endif
  104.     FD_SET(v, set);
  105.     /* add object and its file descriptor to the list */
  106.     if ( index >= FD_SETSIZE ) {
  107.         err_setstr(ValueError, "too many file descriptors in select()");
  108.         return -1;
  109.     }
  110.     fd2obj[index].obj = o;
  111.     fd2obj[index].fd = v;
  112.     fd2obj[++index].obj = (object *)0;    /* sentinel */
  113.     }
  114.     return max+1;
  115. }
  116.  
  117. static object *
  118. set2list(set, fd2obj)
  119.     fd_set *set;
  120.     pylist fd2obj[FD_SETSIZE + 3];
  121. {
  122.     int j, num=0;
  123.     object *list, *o;
  124.     SOCKET fd;
  125.  
  126.     for(j=0; fd2obj[j].obj; j++)
  127.       if ( FD_ISSET(fd2obj[j].fd, set) )
  128.     num++;
  129.     list = newlistobject(num);
  130.     num = 0;
  131.     for(j=0; fd2obj[j].obj; j++) {
  132.       fd = fd2obj[j].fd;
  133.       if ( FD_ISSET(fd, set) ) {
  134. #ifndef _MSC_VER
  135.       if ( fd > FD_SETSIZE ) {
  136.           err_setstr(SystemError,
  137.              "filedescriptor out of range returned in select()");
  138.           return NULL;
  139.       }
  140. #endif
  141.           o = fd2obj[j].obj;
  142.       INCREF(o);
  143.       setlistitem(list, num, o);
  144.       num++;
  145.       }
  146.     }
  147.     return list;
  148. }
  149.  
  150. #ifdef AMITCP
  151.  
  152. /*** AMITCP VERSION OF SELECT: WaitSelect() support ***/
  153. /*** (additional 5th parameter: signal waitmask)    ***/
  154.  
  155. static object *
  156. select_select(self, args)
  157.     object *self;
  158.     object *args;
  159. {
  160.     pylist rfd2obj[FD_SETSIZE + 3], wfd2obj[FD_SETSIZE + 3], efd2obj[FD_SETSIZE + 3];
  161.     object *ifdlist, *ofdlist, *efdlist;
  162.     object *ret, *tout=NULL;
  163.     fd_set ifdset, ofdset, efdset;
  164.     struct timeval tv, *tvp=NULL;
  165.     int seconds;
  166.     int imax, omax, emax, max;
  167.     int n;
  168.     ULONG waitmask=0;
  169.     BOOL do_waitmask = FALSE;
  170.  
  171.     if(newgetargs(args,"OOO|Oi",&ifdlist,&ofdlist,&efdlist,&tout,&waitmask))
  172.     {
  173.         if(tout&&(tout!=None))
  174.         {
  175.             double timeout = PyFloat_AsDouble(tout);
  176.             if(timeout==-1 && PyErr_Occurred()) return NULL;
  177.  
  178.             seconds = (int)timeout;
  179.             timeout -= (double)seconds;
  180.             tv.tv_sec = seconds;
  181.             tv.tv_usec = (int)(timeout*1000000.0);
  182.             tvp = &tv;
  183.         }
  184.     }
  185.     else return NULL;
  186.  
  187.     if(waitmask) do_waitmask=TRUE;
  188.  
  189.     if ( !is_listobject(ifdlist) || !is_listobject(ofdlist) ||
  190.         !is_listobject(efdlist) ) {
  191.         err_badarg();
  192.         return 0;
  193.     }
  194.  
  195.     /* Convert lists to fd_sets, and get maximum fd number */
  196.     if( (imax=list2set(ifdlist, &ifdset, rfd2obj)) < 0 )
  197.       return 0;
  198.     if( (omax=list2set(ofdlist, &ofdset, wfd2obj)) < 0 )
  199.       return 0;
  200.     if( (emax=list2set(efdlist, &efdset, efd2obj)) < 0 )
  201.       return 0;
  202.     max = imax;
  203.     if ( omax > max ) max = omax;
  204.     if ( emax > max ) max = emax;
  205.  
  206.     BGN_SAVE
  207.     n = WaitSelect(max, &ifdset, &ofdset, &efdset, tvp, &waitmask);
  208.     END_SAVE
  209.  
  210.     if ( n < 0 ) {
  211.         err_errno(SelectError);
  212.         return 0;
  213.     }
  214.  
  215.     if ( n == 0 ) { /* Speedup hack */
  216.       ifdlist = newlistobject(0);
  217.       if(do_waitmask)
  218.         ret = mkvalue("(OOOi)", ifdlist, ifdlist, ifdlist, waitmask);
  219.       else
  220.         ret = mkvalue("(OOO)", ifdlist, ifdlist, ifdlist);
  221.       XDECREF(ifdlist);
  222.       return ret;
  223.     }
  224.  
  225.     ifdlist = set2list(&ifdset, rfd2obj);
  226.     ofdlist = set2list(&ofdset, wfd2obj);
  227.     efdlist = set2list(&efdset, efd2obj);
  228.     if(do_waitmask)
  229.         ret = mkvalue("(OOOi)", ifdlist, ofdlist, efdlist, waitmask);
  230.     else
  231.         ret = mkvalue("(OOO)", ifdlist, ofdlist, efdlist);
  232.  
  233.     XDECREF(ifdlist);
  234.     XDECREF(ofdlist);
  235.     XDECREF(efdlist);
  236.     return ret;
  237. }
  238.  
  239.  
  240. static struct methodlist select_methods[] = {
  241.     { "select",    select_select, 1 },
  242.     { 0,    0 ,0 },
  243. };
  244.  
  245.  
  246.  
  247. #else
  248.  
  249. /* this is the original non-AMITCP version: */
  250.  
  251. static object *
  252. select_select(self, args)
  253.     object *self;
  254.     object *args;
  255. {
  256.     pylist rfd2obj[FD_SETSIZE + 3], wfd2obj[FD_SETSIZE + 3], efd2obj[FD_SETSIZE + 3];
  257.     object *ifdlist, *ofdlist, *efdlist;
  258.     object *ret, *tout;
  259.     fd_set ifdset, ofdset, efdset;
  260.     double timeout;
  261.     struct timeval tv, *tvp;
  262.     int seconds;
  263.     int imax, omax, emax, max;
  264.     int n;
  265.  
  266.  
  267.     /* Get args. Looks funny because of optional timeout argument */
  268.     if ( getargs(args, "(OOOO)", &ifdlist, &ofdlist, &efdlist, &tout) ) {
  269.     if (tout == None)
  270.         tvp = (struct timeval *)0;
  271.     else {
  272.         if (!getargs(tout, "d;timeout must be float or None", &timeout))
  273.             return NULL;
  274.         seconds = (int)timeout;
  275.         timeout = timeout - (double)seconds;
  276.         tv.tv_sec = seconds;
  277.         tv.tv_usec = (int)(timeout*1000000.0);
  278.         tvp = &tv;
  279.     }
  280.     } else {
  281.     /* Doesn't have 4 args, that means no timeout */
  282.     err_clear();
  283.     if (!getargs(args, "(OOO)", &ifdlist, &ofdlist, &efdlist) )
  284.       return 0;
  285.     tvp = (struct timeval *)0;
  286.     }
  287.     if ( !is_listobject(ifdlist) || !is_listobject(ofdlist) ||
  288.     !is_listobject(efdlist) ) {
  289.     err_badarg();
  290.     return 0;
  291.     }
  292.  
  293.     /* Convert lists to fd_sets, and get maximum fd number */
  294.     if( (imax=list2set(ifdlist, &ifdset, rfd2obj)) < 0 )
  295.       return 0;
  296.     if( (omax=list2set(ofdlist, &ofdset, wfd2obj)) < 0 )
  297.       return 0;
  298.     if( (emax=list2set(efdlist, &efdset, efd2obj)) < 0 )
  299.       return 0;
  300.     max = imax;
  301.     if ( omax > max ) max = omax;
  302.     if ( emax > max ) max = emax;
  303.  
  304.     BGN_SAVE
  305.     n = select(max, &ifdset, &ofdset, &efdset, tvp);
  306.     END_SAVE
  307.  
  308.     if ( n < 0 ) {
  309.     err_errno(SelectError);
  310.     return 0;
  311.     }
  312.  
  313.     if ( n == 0 ) { /* Speedup hack */
  314.       ifdlist = newlistobject(0);
  315.       ret = mkvalue("OOO", ifdlist, ifdlist, ifdlist);
  316.       XDECREF(ifdlist);
  317.       return ret;
  318.     }
  319.  
  320.     ifdlist = set2list(&ifdset, rfd2obj);
  321.     ofdlist = set2list(&ofdset, wfd2obj);
  322.     efdlist = set2list(&efdset, efd2obj);
  323.     ret = mkvalue("OOO", ifdlist, ofdlist, efdlist);
  324.     XDECREF(ifdlist);
  325.     XDECREF(ofdlist);
  326.     XDECREF(efdlist);
  327.     return ret;
  328. }
  329.  
  330.  
  331. static struct methodlist select_methods[] = {
  332.     { "select",    select_select },
  333.     { 0,    0 },
  334. };
  335.  
  336. #endif /* AMITCP */
  337.  
  338. void
  339. initselect()
  340. {
  341.     object *m, *d;
  342.  
  343. #ifdef AMITCP
  344.         if(!checkbsdsocketlib()) return;
  345. #endif
  346.  
  347.     m = initmodule("select", select_methods);
  348.     d = getmoduledict(m);
  349.     SelectError = newstringobject("select.error");
  350.     if ( SelectError == NULL || dictinsert(d, "error", SelectError) )
  351.       fatal("Cannot define select.error");
  352. }
  353.